package link.chengguo.orangemall.modules.service.sms.impl;

import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import link.chengguo.orangemall.modules.service.sms.ISmsService;
import link.chengguo.orangemall.service.ums.RedisService;
import link.chengguo.orangemall.sys.entity.SysSmsConfig;
import link.chengguo.orangemall.sys.service.SysSmsConfigService;
import link.chengguo.orangemall.ums.entity.Sms;
import link.chengguo.orangemall.ums.mapper.SmsDao;
import link.chengguo.orangemall.util.JsonUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * @Author: mxchen
 * @Date: 2020/9/19 19:15
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SmsServiceImpl implements ISmsService {
    private final RedisService redisService;
    private final IAcsClient acsClient;
    private final SmsDao smsDao;
    private final SysSmsConfigService smsConfigService;
    /**保存短信记录，并发送短信**/
    @Override
    public void saveSmsAndSendMessage(String phone, String code) {
        checkTodaySendCount(phone);

        Sms sms = new Sms();
        sms.setPhone(phone);
        sms.setParams(code);
        Map<String, String> params = new HashMap<>();
        params.put("code", code);
        save(sms, JsonUtils.objectToJson(params));

        //异步调用阿里短信接口发送短信
        CompletableFuture.runAsync(() -> {
            try {
                sendSmsMsg(sms);
            } catch (Exception e) {
                params.put("err", e.getMessage());
                save(sms, JsonUtils.objectToJson(params));
                e.printStackTrace();
                log.error("发送短信失败：{}", e.getMessage());
            }

        });

        // 当天发送短信次数+1
        String countKey = countKey(phone);
        redisService.increment(countKey, 1L);
        redisService.expire(countKey, 1 * 3600 * 24);
    }
    /**限制当天发送短信次数**/
    private void checkTodaySendCount(String phone) {
        SysSmsConfig one = smsConfigService.getOne(new QueryWrapper<>());
        String value = redisService.get(countKey(phone));
        if (value != null) {
            Integer count = Integer.valueOf(value);
            if(count>one.getDayCount()){
                throw new IllegalArgumentException("已超过当天最大次数");
            }
        }

    }

    /**获取缓存中的发送计数**/
    private String countKey(String phone){
        return "sms:count:"+ LocalDate.now().toString()+":"+phone;
    }



    @Override
    public SendSmsResponse sendSmsMsg(Sms sms) {
        SysSmsConfig one = smsConfigService.getOne(new QueryWrapper<>());

        if (sms.getSignName() == null) {
            sms.setSignName(one.getSignName());
        }

        if (sms.getTemplateCode() == null) {
            sms.setTemplateCode(one.getTemplateCode());
        }

        // 阿里云短信官网demo代码
        SendSmsRequest request = new SendSmsRequest();
        request.setSysMethod(MethodType.POST);
        request.setPhoneNumbers(sms.getPhone());
        request.setSignName(sms.getSignName());
        request.setTemplateCode(sms.getTemplateCode());
        request.setTemplateParam(sms.getParams());
        request.setOutId(sms.getId().toString());

        SendSmsResponse response = null;
//		测试时不需要开此 add by someday begin
        try {
            response = acsClient.getAcsResponse(request);
            if (response != null) {
                log.info("发送短信结果：code:{}，message:{}，requestId:{}，bizId:{}", response.getCode(), response.getMessage(),
                        response.getRequestId(), response.getBizId());

                sms.setCode(response.getCode());
                sms.setMessage(response.getMessage());
                sms.setBizId(response.getBizId());
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
//		测试时不需要开此 add by someday end
        update(sms);

        return response;
    }
    @Override
    public Sms findById(Long id) {
        return smsDao.findById(id);
    }

    @Override
    public void save(Sms sms, String params) {
        if (params!=null&&params!="") {
            sms.setParams(params);
        }

        sms.setCreateTime(new Date());
        sms.setUpdateTime(sms.getCreateTime());
        sms.setDay(sms.getCreateTime());

        smsDao.save(sms);
    }

    @Override
    @Transactional
    public void update(Sms sms) {
        sms.setUpdateTime(new Date());
        smsDao.update(sms);
    }





}
